;CAPCOM1990.txt ; A re-assemble-able dis-assembly of the Mega Man 4 sound engine. ; This is also used by Mega Man 3, 5, 6, and most other Capcom NES games released in the 90's. ; Optimized for assembling using ASM6. ; disassembled/commented by Matrixz Nov 2012-Jan 2013 ;Memory labels zC0_playback_disable_and_gradual_fade_lc = $C0 ;Upper 4 bits is Gradual Fade Low Counter. Lower 2 bits disable all playback or BGM playback. zC1_snd_temp1 = $C1 zC2_snd_temp2 = $C2 zC3_snd_temp3 = $C3 zC4_snd_temp4 = $C4 zC5_instrument_pointer = $C5 ;$C6 is covered by label above. zC7_song_frames_to_move = $C7 zC8_speed_low_counter = $C8 zC9_bgm_speed_hi = $C9 zCA_bgm_speed_lo = $CA zCB_global_transpose = $CB zCC_gradual_fade_direction_and_rate = $CC zCD_gradual_fade_level = $CD zCE_current_sfx_priority_level = $CE zCF_sfx_channel_use = $CF zD0_sfx_address_lo = $D0 zD1_sfx_address_hi = $D1 zD2_sfx_transpose = $D2 zD3_sfx_segment_remaining_frames = $D3 zD4_sfx_note_hold_length = $D4 zD5_sfx_segment_remaining_note_down_frames = $D5 zD6_sfx_loop_count_and_mystery_flag = $D6 zD7_sfx_repeat_setting = $D7 zD8_sfx_pitch_add = $D8 ;An explanation of the memory layout: ; Sound effects use Memory $700-$727 while ; Songs (Background music) use $728-$77F. ; For most of the routines, the X register functions ; as a channel index, and index into the memory arrays ; in $700-$77F. ; For sound effects, it's value is 00 to 03. (It's actually ; reverse from the conventional order of the NES channels, so 03 is ; the index for Square 1, while 00 is the index for Noise channel.) ; However, the Song playback routine adds $28 to the X register, ; so the indexes for each channel become $28-$2B instead. ; This allows the engine to use some routines for both Sound effects and BGM. ; For BGM it will read $28 bytes further ahead in RAM and use $728-$7FF instead. ; For the labels below, starting from "m728_data_pointer_low", they are ; only used for music. ; (If seen in a RAM viewer, the addresses of those labels won't make sense unless you keep ; in mind that it actually reads $28 bytes further up because of the X register.) ;Sound effect and Song memory shared labels. ;(#$28 is added to these when handling BGM, using $728-$74F for these datas instead.) m700_current_instrument = $700 m704_stats_and_ADSR_state = $0704 m708_vibrato_count = $708 m70C_channel_register1 = $70C m710_ADSR_current_vol = $0710 m714_pitch_tune = $714 m718_pitch_slide_setting = $718 m71C_current_note = $71C m720_frequency_A = $720 m724_frequency_B = $724 ;BGM-only memory labels (#$28 is added to these too, so the actual address range is $750-$77B.) m728_data_pointer_low = $0728 m72C_data_pointer_high = $072C m730_song_playback_flags = $0730 m734_channel_transpose = $734 m738_note_remaining_time = $738 m73C_note_sustain_length = $73C m740_note_sustain_remaining_time = $740 m744_loop_counters = $744 ;There are 4 loop counters for each channel, so 16 bytes total is devoted to loop counters. ;The only channel memory range which is shared between ;sound effects and songs. ;When used in BGM handling the X register is also plainly the channel index. (#$28 is NOT added in this case.) m77C_last_write_register4 = $77C .ORG $0000 .BASE $8000 ;start at $8000. ;8000, Game engine JSR's here each frame (at end of NMI handler). jmp l806C_PLAY ;8003, Game engine JSR's here for sound initializing. jmp l80FE_INIT ;A = Sound Id. (Can be BGM or SFX, depends on actual data pointed to.) ;If its #$F0-$FF, do a global effect. (if global effect uses Parameter, this must be loaded into Y register). l8006_fraction: ;Modify a value according to another value, that is a fraction of 255. ;Arguments are $C1 and $C4. ;$C1 is the value to modify, the result becomes a fraction of this depending on value of $C4. ;$C4 is the fraction of 255 (numerator, denominator is 255.). This can be anything between 0-255. ;If it's 0, the result becomes 0 as well. ;If $C4 is 255, the result becomes the same as what was stored in $C1 before calling. ;Result is placed in $C1. lda #$00 sta = C000, temporary swap MMC3 bank at ;A000-BFFF, to the extra sound bank and modify pointer ;to read from there. (The Bankšvalue is different from game to game.) sec sbc #$20 sta > 1) sta 00, branch. sta m744_loop_counters,y jsr l8575_cmd4_set_flags ;Set flags, like command 04. The value used to modify the flags is the first byte after the command. (first argument). It's stored in $C3. l8555: ;Read the address that the loop/break command is pointing to, and modify channel's RAM accordingly. jsr l8592_read_data_inc_pointer sta 0 beq l8720 ;If it's 0, don't modify volume rate. tay lda